home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / net / netArp.c < prev    next >
C/C++ Source or Header  |  1991-03-16  |  26KB  |  861 lines

  1. /* 
  2.  * netArp.c --
  3.  *
  4.  *    Routines for net arp and rarp.
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/kernel/net/RCS/netArp.c,v 1.4 91/03/15 15:46:22 jhh Exp Locker: mgbaker $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <sys.h>
  22. #include <stdlib.h>
  23. #include <timer.h>
  24. #include <sync.h>
  25. #include <rpc.h>
  26. #include <netInt.h>
  27. #include <netArp.h>
  28. #include <string.h>
  29. #include <stdio.h>
  30. /*
  31.  * This flag turns on print statements in the ARP protocol
  32.  */
  33. Boolean arpDebug = FALSE;
  34.  
  35. ArpStatistics arpStatistics;
  36.  
  37. /*
  38.  * Current ARP transactions have their state linked together in
  39.  * a list so the packet handler can save the return address for
  40.  * the sender.
  41.  */
  42. static List_Links arpList;
  43. static List_Links revArpList;
  44. static Sync_Semaphore arpListMutex;
  45.  
  46. static ArpOutputQueue arpOutputQueue[ARP_OUTPUT_QUEUE_LEN];
  47. static int nextOutputIndex = 0;
  48.  
  49. static Sync_Lock arpOutputQueueLock; ;
  50. #define LOCKPTR (&arpOutputQueueLock)
  51. static ArpInputQueue arpInputQueue[ARP_INPUT_QUEUE_LEN];
  52. static int nextInputIndex = 0;
  53. static Sync_Semaphore arpInputMutex;
  54.  
  55. static    void    Net_ArpTimeout _ARGS_((Timer_Ticks time, ClientData data));
  56. static    void    NetArpHandler _ARGS_((ClientData data, 
  57.                 Proc_CallInfo *callInfoPtr));
  58. static    void    NetArpOutput _ARGS_((Net_Interface *interPtr,
  59.                 Net_EtherAddress *destEtherAddrPtr,
  60.                 int etherType, NetSpriteArp *requestPtr));
  61. static    void    NetFillInArpRequest _ARGS_((int command, 
  62.                 Net_NetworkType    netType, int protocol,
  63.                 ClientData targetId, ClientData senderId,
  64.                 Net_Address *targetAddrPtr, 
  65.                 Net_Address *senderAddrPtr, 
  66.                 NetSpriteArp *requestPtr));
  67.  
  68. /*
  69.  *----------------------------------------------------------------------
  70.  *
  71.  * Net_ArpInit --
  72.  *
  73.  *    Initializes the arp data structures.
  74.  *
  75.  * Results:
  76.  *    None.
  77.  *
  78.  * Side effects:
  79.  *    None.
  80.  *
  81.  *----------------------------------------------------------------------
  82.  */
  83.  
  84. void
  85. Net_ArpInit()
  86. {
  87.     int i;
  88.  
  89.     Sync_LockInitDynamic(&arpOutputQueueLock, "Net:arpOutputQueueLock");
  90.     Sync_SemInitDynamic(&arpInputMutex, "Net:arpInputMutex");
  91.     Sync_SemInitDynamic(&arpListMutex, "Net:arpListMutex"); 
  92.     /*
  93.      * Mark the arp output queue as all done (output).
  94.      */
  95.     for (i=0; i<ARP_OUTPUT_QUEUE_LEN ; i++) {
  96.     arpOutputQueue[i].gather.done = TRUE;
  97.     }
  98.     List_Init(&arpList);
  99.     List_Init(&revArpList);
  100. }
  101.  
  102.  
  103. /*
  104.  *----------------------------------------------------------------------
  105.  *
  106.  * Net_Arp --
  107.  *
  108.  *      Sprite's Address Resolution Protocol.  Broadcast a Sprite ARP
  109.  *      packet to find the physical address that is used to get to the
  110.  *      host identified by the Sprite ID.
  111.  *
  112.  * Results:
  113.  *    None.
  114.  *
  115.  * Side effects:
  116.  *    A broadcast, and the route table is updated.
  117.  *
  118.  *----------------------------------------------------------------------
  119.  */
  120.  
  121. ReturnStatus
  122. Net_Arp(spriteID, mutexPtr)
  123.     int    spriteID;            /* ID to find the route for */
  124.     Sync_Semaphore *mutexPtr;        /* Address of the mutex that the
  125.                      * caller of Net_Output used for
  126.                      * synchronization.  This needs to
  127.                      * be released during the ARP so that
  128.                      * we can receive our reply. */
  129. {
  130.     ReturnStatus status = FAILURE;
  131.     NetSpriteArp request;        /* The Sprite ARP request packet data */
  132.     NetSpriteArp reply;            /* The Sprite ARP reply packet data */
  133.     Net_ScatterGather gather;        /* Points to packet data */
  134.     Net_Interface *interPtr;
  135.     Net_Route    *routePtr;
  136.     int        i;
  137.  
  138.     for (i = 0; ; i++) {
  139.     routePtr = Net_IDToRoute(NET_BROADCAST_HOSTID, i, FALSE, 
  140.         (Sync_Semaphore *) NIL, 0);
  141.     if (routePtr == (Net_Route *) NIL) {
  142.         break;
  143.     }
  144.     interPtr = routePtr->interPtr;
  145.     NetFillInArpRequest(NET_ARP_REQUEST, interPtr->netType,
  146.         NET_PROTO_RAW,
  147.         (ClientData) spriteID, (ClientData) rpc_SpriteID, 
  148.         &netZeroAddress, &interPtr->netAddress[NET_PROTO_RAW],
  149.         &request);
  150.     gather.bufAddr = (Address)&request;
  151.     gather.length = sizeof(NetSpriteArp);
  152.     gather.done = FALSE;
  153.     gather.mutexPtr = (Sync_Semaphore *) NIL;
  154.     
  155.     status = NetDoArp(routePtr, mutexPtr, NET_ARP_REQUEST, &gather, 
  156.             &reply);
  157.     Net_ReleaseRoute(routePtr);
  158.     if (status == SUCCESS) {
  159.         Net_Address netAddress;
  160.  
  161.         NET_ETHER_ADDR_COPY(* ARP_SRC_ETHER_ADDR(&reply),
  162.         netAddress.ether);
  163.         (void) Net_InstallRoute(spriteID, interPtr, &netAddress,
  164.             NET_PROTO_RAW, "noname", "unknown", 
  165.             (ClientData) 0);
  166.         return status;
  167.     }
  168.     }
  169.     return status;
  170. }
  171.  
  172. /*
  173.  *----------------------------------------------------------------------
  174.  *
  175.  * Net_RevArp --
  176.  *
  177.  *      Sprite's Reverse Address Resolution Protocol.  Broadcast a Sprite
  178.  *      Reverse ARP packet to find the Sprite ID or Internet address
  179.  *    that corresponds to our network address.
  180.  *
  181.  * Results:
  182.  *    A Sprite host ID
  183.  *
  184.  * Side effects:
  185.  *    None.
  186.  *
  187.  *----------------------------------------------------------------------
  188.  */
  189.  
  190. int
  191. Net_RevArp(routePtr, protocol, netAddressPtr, mutexPtr)
  192.     Net_Route        *routePtr;    /* The route to use for the arp.*/
  193.     int            protocol;    /* Which protocol we are trying
  194.                      * to resolve an address for. */
  195.     Net_Address        *netAddressPtr; /* The address we are trying to 
  196.                      * resolve. */
  197.     Sync_Semaphore    *mutexPtr;    /* Mutex to release. */
  198. {
  199.     ReturnStatus status;
  200.     NetSpriteArp request;        /* Sprite RARP request packet data */
  201.     NetSpriteArp reply;            /* Sprite RARP reply packet data */
  202.     Net_ScatterGather gather;        /* Points to packet data */
  203.     Net_Interface    *interPtr;
  204.  
  205.     interPtr = routePtr->interPtr;
  206.     if (netAddressPtr == (Net_Address *) NIL) {
  207.     netAddressPtr = &interPtr->netAddress[NET_PROTO_RAW];
  208.     }
  209.     NetFillInArpRequest(NET_RARP_REQUEST, interPtr->netType,
  210.         protocol, 
  211.         (ClientData) 0, (ClientData) 0,
  212.         netAddressPtr,
  213.         &interPtr->netAddress[NET_PROTO_RAW], 
  214.         &request);
  215.     gather.bufAddr = (Address)&request;
  216.     gather.length = sizeof(NetSpriteArp);
  217.     gather.done = FALSE;
  218.     gather.mutexPtr = (Sync_Semaphore *) NIL;
  219.  
  220.     status = NetDoArp(routePtr, mutexPtr, NET_RARP_REQUEST, &gather, 
  221.     &reply);
  222.     if (status == SUCCESS) {
  223.     unsigned int value;
  224.     bcopy(ARP_TARGET_PROTO_ADDR(&reply),(char *) &value,4);
  225.     return(Net_NetToHostInt(value));
  226.     } 
  227.     return -1;
  228. }
  229.  
  230. /*
  231.  *----------------------------------------------------------------------
  232.  *
  233.  * NetDoArp --
  234.  *
  235.  *    The broadcast-retry-wait loop for ARP and Reverse Arp.
  236.  *
  237.  * Results:
  238.  *    Fills in the callers packet buffer with a copy of the reply.
  239.  *    Returns FAILURE if there is no response after a timeout.
  240.  *
  241.  * Side effects:
  242.  *    The packet broadcast, wait, etc.
  243.  *
  244.  *----------------------------------------------------------------------
  245.  */
  246.  
  247. ReturnStatus
  248. NetDoArp(routePtr, mutexPtr, command, gatherPtr, packetPtr)
  249.     Net_Route        *routePtr;    /* The route to use for the arp. */
  250.     Sync_Semaphore *mutexPtr;        /* Address of the mutex that the
  251.                      * caller of Net_Output used for
  252.                      * synchronization.  This needs to
  253.                      * be released during the ARP so that
  254.                      * we can receive our reply. */
  255.     int command;            /* NET_ARP_REQUEST or NET_RARP_REQUEST*/
  256.     Net_ScatterGather *gatherPtr;    /* Specifies the output packet */
  257.     NetSpriteArp *packetPtr;        /* Filled in with the reply packet */
  258. {
  259.     register Net_EtherHdr *etherHdrPtr;    /* Regular RPC broadcast header */
  260.     Net_EtherHdr etherHdr;        /* Header for Sprite ARP packet */
  261.     int retries = 0;            /* Retry counter */
  262.     ArpState arp;            /* State for the protocol */
  263.     NetSpriteArp *requestPtr;        /* Pointer to request data */
  264.     List_Links *listPtr;        /* Either arpList or revArpList */
  265.     Net_Interface     *interPtr;    /* Network interface. */
  266.  
  267.     /*
  268.      * If we are aren't passed a mutexPtr then assume we can't do an
  269.      * Arp.  This is because we are either at interrupt level or there
  270.      * are high-level locks that cannot be released.
  271.      */
  272.     if (mutexPtr == (Sync_Semaphore *) NIL) {
  273.     return FAILURE;
  274.     }
  275.     if (Mach_AtInterruptLevel()) {
  276.     panic("NetDoArp: at interrupt level!!!");
  277.     }
  278.     interPtr = routePtr->interPtr;
  279.     switch(interPtr->netType) {
  280.     case NET_NETWORK_ETHER : {
  281.         /*
  282.          * Set up the ethernet header for the Arp request packet.  We can't
  283.          * use the regular broadcast route because the ethernet protocol 
  284.          * type is different, Arp.  The broadcast destination address,
  285.          * however, is obtained from the regular broadcast route.
  286.          */
  287.         etherHdrPtr = (Net_EtherHdr *)routePtr->headerPtr[NET_PROTO_RAW];
  288.         NET_ETHER_ADDR_COPY(NET_ETHER_HDR_DESTINATION(*etherHdrPtr),
  289.                 NET_ETHER_HDR_DESTINATION(etherHdr));
  290.         if (command == NET_ARP_REQUEST) {
  291.         NET_ETHER_HDR_TYPE(etherHdr) = 
  292.             Net_HostToNetShort(NET_ETHER_ARP);
  293.         } else {
  294.         NET_ETHER_HDR_TYPE(etherHdr) = 
  295.             Net_HostToNetShort(NET_ETHER_REVARP);
  296.         }
  297.         break;
  298.     }
  299.     default:
  300.         printf("NetDoArp :Invalid route (bad network type %d)\n", 
  301.         routePtr->interPtr->netType);
  302.         return FAILURE;
  303.     }
  304.     requestPtr = (NetSpriteArp *)gatherPtr->bufAddr;
  305.     /*
  306.      * Use a simple retry loop to get our reply.  The ARP protocol state
  307.      * is set up and put on a list so the packet handler can find it.
  308.      */
  309.  
  310.     arp.state = ARP_WANT_REPLY;
  311.     arp.mutexPtr = mutexPtr;
  312.     arp.type = Net_NetToHostShort((requestPtr->arpHeader.protocolType));
  313.  
  314.     if (command == NET_ARP_REQUEST) {
  315.     int spriteID;
  316.     bcopy(ARP_TARGET_PROTO_ADDR(requestPtr),(char *) &spriteID,4);
  317.     arp.id =  (ClientData) Net_NetToHostInt((unsigned int)spriteID);
  318.     listPtr = &arpList;
  319.     } else {
  320.     arp.id = (ClientData) ARP_TARGET_ETHER_ADDR(requestPtr);
  321.     listPtr = &revArpList;
  322.     }
  323.     MASTER_LOCK(&arpListMutex);
  324.     List_InitElement((List_Links *) &arp);
  325.     List_Insert((List_Links *)&arp, LIST_ATREAR(listPtr));
  326.     MASTER_UNLOCK(&arpListMutex);
  327.  
  328.     while (retries < 4 && ((arp.state & ARP_HAVE_INPUT) == 0)) {
  329.     retries++;
  330.     if (command == NET_ARP_REQUEST) {
  331.         if (arpDebug) {
  332.         printf("Sending arp request for %d\n", arp.id);
  333.         }
  334.         arpStatistics.numArpRequests++;
  335.     } else {
  336.         if (arpDebug) {
  337.         printf("Sending rev arp request\n");
  338.         }
  339.         arpStatistics.numRevArpRequests++;
  340.     }
  341.     (void) (interPtr->output)(interPtr, (Address) ðerHdr, gatherPtr, 1, 
  342.             FALSE, (ReturnStatus *) NIL);
  343.  
  344.     arp.state |= ARP_IN_TIMEOUT_QUEUE ;
  345.     arp.timeout.routine = Net_ArpTimeout;
  346.     arp.timeout.interval = 500 * timer_IntOneMillisecond;
  347.     arp.timeout.clientData = (ClientData)&arp;
  348.     Timer_ScheduleRoutine(&arp.timeout, TRUE);
  349.     do {
  350.         Sync_MasterWait(&arp.condition, arp.mutexPtr, FALSE);
  351.     } while (((arp.state & ARP_HAVE_INPUT) == 0) &&
  352.          (arp.state & ARP_IN_TIMEOUT_QUEUE));
  353.     }
  354.     MASTER_LOCK(&arpListMutex);
  355.     List_Remove((List_Links *)&arp);
  356.     MASTER_UNLOCK(&arpListMutex);
  357.     if (arp.state & ARP_IN_TIMEOUT_QUEUE) {
  358.     Timer_DescheduleRoutine(&arp.timeout);
  359.     }
  360.  
  361.     if ((arp.state & ARP_HAVE_INPUT) == 0) {
  362.     arpStatistics.numTimeouts++;
  363.     return(FAILURE);
  364.     } else {
  365.     *packetPtr = arp.packet;
  366.     return(SUCCESS);
  367.     }    
  368. }
  369.  
  370. /*
  371.  *----------------------------------------------------------------------
  372.  *
  373.  * NetArpInput --
  374.  *
  375.  *    Handler for the Address Resolution Protocol.  This looks through
  376.  *    the list of arpState's to find a match between the Sprite IDs.
  377.  *    Upon a match the physical address from the reply is stored in
  378.  *    the state and the waiting process is notified.
  379.  *
  380.  * Results:
  381.  *    None.
  382.  *
  383.  * Side effects:
  384.  *    Copies the data from the arp reply into the arp state that
  385.  *    was enqueued in arpList by Net_Arp.  The arpState is marked
  386.  *    as having received input.
  387.  *
  388.  *----------------------------------------------------------------------
  389.  */
  390.  
  391. /*ARGSUSED*/
  392. void
  393. NetArpInput(interPtr, packetPtr, packetLength)
  394.     Net_Interface    *interPtr;    /* The interface that got the 
  395.                      * packet. */
  396.     Address packetPtr;        /* Pointer to the packet in the hardware
  397.                  * recieve buffers */
  398.     int packetLength;        /* Length of the packet */
  399. {
  400.     register NetSpriteArp *arpDataPtr;
  401.     Boolean    forKernel = TRUE;
  402.     short opcode, type;
  403.  
  404.     switch(interPtr->netType) {
  405.     case NET_NETWORK_ETHER: {
  406.         arpDataPtr = (NetSpriteArp *)(packetPtr + sizeof(Net_EtherHdr));
  407.         break;
  408.     }
  409.     default :
  410.         return;
  411.     }
  412.     opcode = Net_NetToHostShort(arpDataPtr->arpHeader.opcode);
  413.     type = Net_NetToHostShort(arpDataPtr->arpHeader.protocolType);
  414.     /*
  415.      * This packet is for the kernel ARP if the following 
  416.      * condition are true:
  417.      *    1) The hardwareType of the request is for the ethernet.
  418.      *  2) The protocolType is ether for IP or Sprite type.
  419.      *  3) The opcode is one we can handle (1 thru 4).
  420.      */
  421.     forKernel = (Net_NetToHostShort(arpDataPtr->arpHeader.hardwareType) == 
  422.                         NET_ARP_TYPE_ETHER)      &&
  423.          ((type == NET_ETHER_IP) || (type == NET_ETHER_SPRITE)) &&
  424.          ((opcode > 0) && (opcode < 5)) ;
  425.  
  426.     if (!forKernel) {
  427.     return;
  428.     }
  429.  
  430.     switch (opcode) {
  431.     case NET_ARP_REQUEST: {
  432.         unsigned int id;
  433.         /*
  434.          * Received a request for the address corresponding to a
  435.          * sprite ID. Look to see if it is for us.
  436.          * If it is then we reply with that info.
  437.          */
  438.         bcopy(ARP_TARGET_PROTO_ADDR(arpDataPtr),(char *)&id,4);
  439.         id = Net_NetToHostInt(id);
  440.         if (arpDebug) {
  441.         printf("Got ARP request for Sprite ID 0x%x\n", id);
  442.         }
  443.         if (type == NET_ETHER_SPRITE) { 
  444.         forKernel = (id == rpc_SpriteID);
  445.         } else {
  446.         forKernel = (id == interPtr->netAddress[NET_PROTO_INET].inet);
  447.         }
  448.         if (forKernel) { 
  449.         /*
  450.          * We might overrun ourselves if we get a whole
  451.          * bunch of arp requests.  We synchronize, however,
  452.          * so that the call-back procedure sees a 
  453.          * consistent view.
  454.          */
  455.         register ArpInputQueue *arpInputPtr;
  456.         MASTER_LOCK(&arpInputMutex);
  457.         arpInputPtr = &arpInputQueue[nextInputIndex];
  458.         arpInputPtr->interPtr = interPtr;
  459.         arpInputPtr->packet = *arpDataPtr;
  460.         nextInputIndex = (nextInputIndex + 1) % ARP_INPUT_QUEUE_LEN;
  461.         MASTER_UNLOCK(&arpInputMutex);
  462.         Proc_CallFunc(NetArpHandler, (ClientData)arpInputPtr, 0);
  463.         }
  464.         break;
  465.     }
  466.     case NET_ARP_REPLY: {
  467.         ArpState *arpPtr;
  468.         unsigned int id;
  469.         Net_EtherAddress *targetEtherAddrPtr;
  470.  
  471.         /*
  472.          * Make sure this REPLY is targeted for us.
  473.          */
  474.         targetEtherAddrPtr = 
  475.             (Net_EtherAddress *)ARP_TARGET_ETHER_ADDR(arpDataPtr);
  476.         if (!NET_ETHER_COMPARE_PTR(
  477.             &interPtr->netAddress[NET_PROTO_RAW].ether,
  478.             targetEtherAddrPtr)) {
  479.         break;
  480.         }
  481.  
  482.         /*
  483.          * Look through the list of active arp requests for the one
  484.          * that matches this reply.  Then just copy the arp data to
  485.          * that state and notify the waiting process.
  486.          * Note: we'll probably get many replies to each arp request
  487.          * and only the first one updates the waiting process's arp
  488.          * state.  This is probably overly paranoid, but we don't want
  489.          * to be messing with things once we've notified the waiter.
  490.          */
  491.         bcopy(ARP_SRC_PROTO_ADDR(arpDataPtr),(char *)&id,4);
  492.         id = Net_NetToHostInt(id);
  493.         if (arpDebug) {
  494.         printf("Got ARP reply for type %d Id 0x%x\n", type, id);
  495.         }
  496.         MASTER_LOCK(&arpListMutex);
  497.         LIST_FORALL(&arpList, (List_Links *)arpPtr) {
  498.         if ((arpPtr->id == (ClientData) id) && (arpPtr->type == type)) {
  499.             if ((arpPtr->state & ARP_HAVE_INPUT) == 0) {
  500.             arpPtr->packet = *arpDataPtr;
  501.             arpPtr->state |= ARP_HAVE_INPUT;
  502.             Sync_MasterBroadcast(&arpPtr->condition);
  503.             if (arpDebug) {
  504.                 printf("Woke ARP list type %d id %d\n",arpPtr->type,
  505.                 arpPtr->id);
  506.             }
  507.             }
  508.         }
  509.         }
  510.         MASTER_UNLOCK(&arpListMutex);
  511.         break;
  512.     }
  513.     case NET_RARP_REQUEST: {
  514.         /*
  515.          * Look in our route table for an entry with the ethernet
  516.          * address of the sender.  If one is found, return a reply
  517.          * containing the corresponding Sprite ID. The kernel only
  518.          * handles NET_ETHER_SPRITE requests.
  519.          */
  520.         int     spriteID;
  521.         Net_Address netAddress;
  522.         if (type == NET_ETHER_SPRITE) { 
  523.         NET_ETHER_ADDR_COPY(* (Net_EtherAddress *) 
  524.             ARP_TARGET_ETHER_ADDR(arpDataPtr),
  525.             netAddress.ether);
  526.  
  527.         spriteID = Net_AddrToID(interPtr->netType, NET_PROTO_RAW,
  528.             &netAddress);
  529.         if (arpDebug) {
  530.             printf("Got REV_ARP request for Sprite ID 0x%x\n",
  531.                 spriteID);
  532.         }
  533.         if (spriteID > 0) {
  534.             register ArpInputQueue *arpInputPtr;
  535.             MASTER_LOCK(&arpInputMutex);
  536.             arpInputPtr = &arpInputQueue[nextInputIndex];
  537.             arpInputPtr->interPtr = interPtr;
  538.             arpInputPtr->packet = *arpDataPtr;
  539.             nextInputIndex = (nextInputIndex + 1) % 
  540.                             ARP_INPUT_QUEUE_LEN;
  541.             MASTER_UNLOCK(&arpInputMutex);
  542.             Proc_CallFunc(NetArpHandler, (ClientData)arpInputPtr,0);
  543.         }
  544.          }
  545.     }
  546.     case NET_RARP_REPLY: {
  547.         ArpState *arpPtr;
  548.         Net_EtherAddress *targetEtherAddrPtr;
  549.  
  550.         targetEtherAddrPtr = 
  551.             (Net_EtherAddress *)ARP_TARGET_ETHER_ADDR(arpDataPtr);
  552.         if (!NET_ETHER_COMPARE_PTR(
  553.             &interPtr->netAddress[NET_PROTO_RAW].ether,
  554.             targetEtherAddrPtr)) {
  555.         break;
  556.         }
  557.         /*
  558.          * Make sure there is still a waiting process for this reply,
  559.          * then copy the reply into the waiting arp state.
  560.          */
  561.         if (arpDebug) {
  562.           printf("Got REV_ARP reply for type %d\n",type);
  563.         }
  564.         MASTER_LOCK(&arpListMutex);
  565.         LIST_FORALL(&revArpList, (List_Links *)arpPtr) {
  566.         if ((arpPtr->type == type) && 
  567.             NET_ETHER_COMPARE_PTR(targetEtherAddrPtr,
  568.                      (Net_EtherAddress *) (arpPtr->id))) {
  569.             if ((arpPtr->state & ARP_HAVE_INPUT) == 0) {
  570.             arpPtr->packet = *arpDataPtr;
  571.             arpPtr->state |= ARP_HAVE_INPUT;
  572.             Sync_MasterBroadcast(&arpPtr->condition);
  573.             if (arpDebug) {
  574.               printf("Woke REV_ARP reply for type %d\n",type);
  575.             }
  576.             }
  577.         }
  578.         }
  579.         MASTER_UNLOCK(&arpListMutex);
  580.         break;
  581.     }
  582.     }
  583.     return;
  584. }
  585.  
  586. /*
  587.  *----------------------------------------------------------------------
  588.  *
  589.  * NetArpHandler --
  590.  *
  591.  *    Routine to send an arp reply.  Called via Proc_CallFunc.
  592.  *    This returns an ethernet address given a Sprite ID.  The
  593.  *    interrupt handler has already checked in the netRouteArray for
  594.  *    a good route for the spriteID.
  595.  *
  596.  * Results:
  597.  *    None.
  598.  *
  599.  * Side effects:
  600.  *    Generates a  arp reply packet.
  601.  *
  602.  *----------------------------------------------------------------------
  603.  */
  604. /*ARGSUSED*/
  605. static void
  606. NetArpHandler(data, callInfoPtr)
  607.     ClientData data;        /* Pointer into arpInputQueue */
  608.     Proc_CallInfo *callInfoPtr;
  609. {
  610.     Net_Interface    *interPtr;
  611.     ArpInputQueue *arpInputPtr = (ArpInputQueue *)data;
  612.     NetSpriteArp   *arpDataPtr, request;
  613.     unsigned short opcode, type;
  614.  
  615.     MASTER_LOCK(&arpInputMutex);
  616.  
  617.     interPtr = arpInputPtr->interPtr;
  618.     arpDataPtr = &arpInputPtr->packet;
  619.     opcode = Net_NetToHostShort(arpDataPtr->arpHeader.opcode);
  620.     type = Net_NetToHostShort(arpDataPtr->arpHeader.protocolType);
  621.  
  622.     if ((type != NET_ETHER_SPRITE) && (type != NET_ETHER_IP)) {
  623.     MASTER_UNLOCK(&arpInputMutex);
  624.     panic("Bad type %d in NetArpHandler\n", type);
  625.     return;
  626.     } 
  627.     if (opcode == NET_ARP_REQUEST) {
  628.     Net_Address    netAddress;
  629.  
  630.     NET_ETHER_ADDR_COPY(
  631.         * (Net_EtherAddress *) ARP_SRC_ETHER_ADDR(arpDataPtr), 
  632.         netAddress.ether);
  633.     if (type == NET_ETHER_SPRITE) {
  634.         int    spriteID;
  635.         bcopy(ARP_SRC_PROTO_ADDR(arpDataPtr),(char*)&spriteID,sizeof(int));
  636.  
  637.         NetFillInArpRequest(NET_ARP_REPLY, interPtr->netType,
  638.         NET_PROTO_RAW,
  639.         (ClientData) spriteID, (ClientData) rpc_SpriteID, 
  640.         &netAddress, &interPtr->netAddress[NET_PROTO_RAW],
  641.         &request);
  642.     } else {
  643.         Net_Address        inetAddress;
  644.         Net_InetAddress inetAddr;
  645.         bcopy(ARP_SRC_PROTO_ADDR(arpDataPtr), (char *)&inetAddress.inet, 
  646.             sizeof(inetAddr));
  647.  
  648.         NetFillInArpRequest(NET_ARP_REPLY, interPtr->netType, 
  649.         NET_PROTO_INET,
  650.         (ClientData) inetAddress.inet, 
  651.         (ClientData)  interPtr->netAddress[NET_PROTO_INET].inet, 
  652.         &netAddress, &interPtr->netAddress[NET_PROTO_RAW],
  653.         &request);
  654.     }
  655.         NetArpOutput(interPtr, &netAddress.ether, NET_ETHER_ARP, &request);
  656.     } else if (opcode == NET_RARP_REQUEST) {
  657.     Net_Address netAddress;
  658.     int    spriteID;
  659.     NET_ETHER_ADDR_COPY(
  660.         *(Net_EtherAddress *)ARP_TARGET_ETHER_ADDR(arpDataPtr),
  661.         netAddress.ether);
  662.     spriteID = Net_AddrToID(interPtr->netType, NET_PROTO_RAW, &netAddress);
  663.     if (spriteID > 0) { 
  664.         NetFillInArpRequest(NET_RARP_REPLY, interPtr->netType,
  665.             NET_PROTO_RAW,
  666.             (ClientData) spriteID, (ClientData) rpc_SpriteID,
  667.             &netAddress, &interPtr->netAddress[NET_PROTO_RAW],
  668.             &request);
  669.         NetArpOutput(interPtr, (Net_EtherAddress *) ARP_SRC_ETHER_ADDR(arpDataPtr),
  670.             NET_ETHER_REVARP, &request);
  671.     }
  672.     } else {
  673.     MASTER_UNLOCK(&arpInputMutex);
  674.     panic ("Bad opcode %d in NetArpHandler\n", opcode);
  675.     return;
  676.     }
  677.     MASTER_UNLOCK(&arpInputMutex);
  678.  
  679.     callInfoPtr->interval = 0;
  680.     return;
  681. }
  682.  
  683. /*
  684.  *----------------------------------------------------------------------
  685.  *
  686.  * NetArpOutput --
  687.  *
  688.  *    Routine to send an arp packet.
  689.  *
  690.  * Results:
  691.  *    None.
  692.  *
  693.  * Side effects:
  694.  *    Generates a Sprite arp packet.
  695.  *
  696.  *----------------------------------------------------------------------
  697.  */
  698. /*ARGSUSED*/
  699. static void
  700. NetArpOutput(interPtr, destEtherAddrPtr, etherType, requestPtr)
  701.     Net_Interface    *interPtr;
  702.     Net_EtherAddress *destEtherAddrPtr;    /* Host to send to */
  703.     int        etherType;        /* Type of ethernet packet to send. */
  704.     NetSpriteArp *requestPtr;        /* Request to send. */
  705. {
  706.     register Net_EtherHdr  *etherHdrPtr;
  707.     register Net_ScatterGather *gatherPtr;
  708.     register NetSpriteArp *packetPtr;
  709.  
  710.     if (interPtr->netType != NET_NETWORK_ETHER) {
  711.     printf("NetArpOutput: invalid network type %d\n", interPtr->netType);
  712.     return;
  713.     }
  714.     LOCK_MONITOR;
  715.  
  716.  
  717.     etherHdrPtr = &arpOutputQueue[nextOutputIndex].etherHdr;
  718.     packetPtr = &arpOutputQueue[nextOutputIndex].packet;
  719.     gatherPtr = &arpOutputQueue[nextOutputIndex].gather;
  720.     if (! gatherPtr->done) {
  721.     printf("Warning: NetArpOutput can't queue packet");
  722.     UNLOCK_MONITOR;
  723.     return;
  724.     }
  725.     nextOutputIndex = (nextOutputIndex + 1) % ARP_OUTPUT_QUEUE_LEN;
  726.  
  727.     NET_ETHER_ADDR_COPY(*destEtherAddrPtr, 
  728.             NET_ETHER_HDR_DESTINATION(*etherHdrPtr));
  729.     NET_ETHER_HDR_TYPE(*etherHdrPtr) = 
  730.         Net_HostToNetShort((unsigned short)etherType);
  731. #ifdef sun4
  732.     /*
  733.      * Gcc for the sun4 currently allows these structures to be on unaligned
  734.      * boundaries and then generates loads and stores as if they were aligned,
  735.      * so I have to copy them byte by byte.
  736.      */
  737.      bcopy((char *)requestPtr, (char *)packetPtr, sizeof (NetSpriteArp));
  738. #else
  739.     *packetPtr = *requestPtr;
  740. #endif sun4
  741.  
  742.     gatherPtr->bufAddr = (Address)packetPtr;
  743.     gatherPtr->length = sizeof(NetSpriteArp);
  744.     gatherPtr->done = FALSE;
  745.     gatherPtr->mutexPtr = (Sync_Semaphore *) NIL;
  746.  
  747.     arpStatistics.numRevArpReplies++;
  748.     (void) (interPtr->output)(interPtr, (Address) etherHdrPtr, gatherPtr, 1, 
  749.     FALSE, (ReturnStatus *) NIL);
  750.  
  751.     UNLOCK_MONITOR;
  752.     return;
  753. }
  754.  
  755. /*
  756.  *----------------------------------------------------------------------
  757.  *
  758.  * Net_ArpTimeout --
  759.  *
  760.  *    Timeout routine for ARP.  This just notifies the waiting process.
  761.  *
  762.  * Results:
  763.  *    None.
  764.  *
  765.  * Side effects:
  766.  *    Wakes up the process waiting for an ARP reply.
  767.  *
  768.  *----------------------------------------------------------------------
  769.  */
  770. /*ARGSUSED*/
  771. static void
  772. Net_ArpTimeout(time, data)
  773.     Timer_Ticks time;        /* The time we timed out at. */
  774.     ClientData data;        /* Out private data is a pointer to the
  775.                  * arp protocol state. */
  776. {
  777.     ArpState *arpPtr = (ArpState *)data;    
  778.  
  779.     MASTER_LOCK(arpPtr->mutexPtr);
  780.     if (arpDebug) {
  781.     printf("Arp timeout\n");
  782.     }
  783.     arpPtr->state &= ~ARP_IN_TIMEOUT_QUEUE;
  784.     Sync_MasterBroadcast(&arpPtr->condition);
  785.     MASTER_UNLOCK(arpPtr->mutexPtr);
  786.     return;
  787. }
  788.  
  789. /*
  790.  *----------------------------------------------------------------------
  791.  *
  792.  * NetFillInArpRequest --
  793.  *
  794.  *     Build a ARP or RARP packet in the provided request buffer.
  795.  *
  796.  * Results:
  797.  *    None.
  798.  *
  799.  * Side effects:
  800.  *    None.
  801.  *
  802.  *----------------------------------------------------------------------
  803.  */
  804.  
  805. static void
  806. NetFillInArpRequest(command, netType, protocol, targetId, senderId, 
  807.     targetAddrPtr, senderAddrPtr, requestPtr)
  808.     short    command;    /* ARP opcode to perform. */
  809.     Net_NetworkType    netType;
  810.     int            protocol;
  811.     ClientData    targetId;    /* Target protocol address. */
  812.     ClientData  senderId;    /* Sender's protocol ID. */
  813.     Net_Address    *targetAddrPtr; /* Target network address. */
  814.     Net_Address    *senderAddrPtr; /* Sender'network address. */
  815.     NetSpriteArp *requestPtr;    /* Arp request packet to fill in. */
  816. {
  817.     unsigned int tid;
  818.     unsigned int sid;
  819.  
  820.     switch (netType) {
  821.     case NET_NETWORK_ETHER: {
  822.         requestPtr->arpHeader.hardwareType = 
  823.             Net_HostToNetShort(NET_ARP_TYPE_ETHER);
  824.         requestPtr->arpHeader.hardwareAddrLen = sizeof(Net_EtherAddress);
  825.         requestPtr->arpHeader.opcode = 
  826.             Net_HostToNetShort((unsigned short)command);
  827.         switch (protocol) {
  828.         case NET_PROTO_RAW: {
  829.             requestPtr->arpHeader.protocolType = 
  830.                 Net_HostToNetShort(NET_ETHER_SPRITE);
  831.             requestPtr->arpHeader.protocolAddrLen = sizeof(int);
  832.             break;
  833.         }
  834.         case NET_PROTO_INET: {
  835.             requestPtr->arpHeader.protocolType = 
  836.                 Net_HostToNetShort(NET_ETHER_IP);
  837.             requestPtr->arpHeader.protocolAddrLen = 
  838.             sizeof(Net_InetAddress);
  839.             break;
  840.         }
  841.         default:
  842.             panic("NetFillInArpRequest: Unknown protocol %d\n", 
  843.             protocol);
  844.         }
  845.         NET_ETHER_ADDR_COPY(targetAddrPtr->ether,
  846.             *(Net_EtherAddress *)ARP_TARGET_ETHER_ADDR(requestPtr));
  847.         NET_ETHER_ADDR_COPY(senderAddrPtr->ether,
  848.             *(Net_EtherAddress *)ARP_SRC_ETHER_ADDR(requestPtr));
  849.         break;
  850.     }
  851.     default: {
  852.         panic("Warning: NetFillInArpRequest: bad netType %d\n", netType);
  853.     }
  854.     }
  855.     tid = Net_HostToNetInt((unsigned int) targetId);
  856.     sid = Net_HostToNetInt((unsigned int) senderId);
  857.     bcopy((char *) &sid, ARP_SRC_PROTO_ADDR(requestPtr),sizeof(int));
  858.     bcopy((char *) &tid, ARP_TARGET_PROTO_ADDR(requestPtr),sizeof(int));
  859.     return;
  860. }
  861.